-----------------------------------------------------------------
--ECE 251 Switch - 32-bit CRC Register block                   --
--by Colin Anderson and frame by Peter Gebhard                 --
--Given 4 bits of new frame data, this recalculates the CRC of---
--the whole frame.  
--When check valid is true, The CRCregister will be checked for--
--equality with the validity_reg input extracted from the frame-- 
-----------------------------------------------------------------
--polynomial 0 1 2 4 5 7 8 10 11 12 16 22 23 26 32 
--
--CRC algoritm based on "CRC Tool" from www.easics.com
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY CRC IS
   --GENERIC(N:INTEGER:=4);
	PORT(clk     		: IN   STD_LOGIC;
		frame_done		: IN   STD_LOGIC;	  
		d 	      		: IN   STD_LOGIC_VECTOR(3 DOWNTO 0);
        data_valid		: IN   STD_LOGIC;

--		d2				:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
		check_complete 	: OUT  STD_LOGIC;
        crc_valid 		: OUT  STD_LOGIC;       
        crc_outputReg	: OUT	STD_LOGIC_VECTOR(31 DOWNTO 0)
		);
END CRC;

ARCHITECTURE Behavior OF CRC IS

shared variable CRCregister: STD_LOGIC_VECTOR(31 DOWNTO 0);
shared variable CRCcopy: STD_LOGIC_VECTOR(31 DOWNTO 0);
shared variable CRCR2: STD_LOGIC_VECTOR(31 DOWNTO 0);
shared variable d2:	STD_LOGIC_VECTOR(3 DOWNTO 0);


	BEGIN
	   PROCESS (clk)
	   BEGIN
			
			
			IF (clk'EVENT AND clk = '1') THEN
			
			------------------------------------------


			-------------------------------------------
			check_complete <= '0';	
			crc_valid <= '0';
			
			IF (data_valid = '0' )THEN
			CRCregister := "11111111111111111111111111111111";
--			 CRCregister := "10000010011000001000111011011011";
			ELSE --if data_valid is 1
				CRCcopy := CRCregister;
			
			
			------------------------------------------
			--Calculating the 32bit CRC based on the 4bit input
			---------
		    CRCregister(0) := d(0) xor CRCcopy(28);
		    CRCregister(1) := d(1) xor d(0) xor CRCcopy(28) xor CRCcopy(29);
		    CRCregister(2) := d(2) xor d(1) xor d(0) xor CRCcopy(28) xor CRCcopy(29) xor CRCcopy(30);
		    CRCregister(3) := d(3) xor d(2) xor d(1) xor CRCcopy(29) xor CRCcopy(30) xor CRCcopy(31);
		    CRCregister(4) := d(3) xor d(2) xor d(0) xor CRCcopy(0) xor CRCcopy(28) xor CRCcopy(30) xor 
		                 CRCcopy(31);
		    CRCregister(5) := d(3) xor d(1) xor d(0) xor CRCcopy(1) xor CRCcopy(28) xor CRCcopy(29) xor 
		                 CRCcopy(31);
		    CRCregister(6) := d(2) xor d(1) xor CRCcopy(2) xor CRCcopy(29) xor CRCcopy(30);
		    CRCregister(7) := d(3) xor d(2) xor d(0) xor CRCcopy(3) xor CRCcopy(28) xor CRCcopy(30) xor 
		                 CRCcopy(31);
		    CRCregister(8) := d(3) xor d(1) xor d(0) xor CRCcopy(4) xor CRCcopy(28) xor CRCcopy(29) xor 
		                 CRCcopy(31);
		    CRCregister(9) := d(2) xor d(1) xor CRCcopy(5) xor CRCcopy(29) xor CRCcopy(30);
		    CRCregister(10) := d(3) xor d(2) xor d(0) xor CRCcopy(6) xor CRCcopy(28) xor CRCcopy(30) xor 
		                  CRCcopy(31);
		    CRCregister(11) := d(3) xor d(1) xor d(0) xor CRCcopy(7) xor CRCcopy(28) xor CRCcopy(29) xor 
		                  CRCcopy(31);
		    CRCregister(12) := d(2) xor d(1) xor d(0) xor CRCcopy(8) xor CRCcopy(28) xor CRCcopy(29) xor 
		                  CRCcopy(30);
		    CRCregister(13) := d(3) xor d(2) xor d(1) xor CRCcopy(9) xor CRCcopy(29) xor CRCcopy(30) xor 
		                  CRCcopy(31);
		    CRCregister(14) := d(3) xor d(2) xor CRCcopy(10) xor CRCcopy(30) xor CRCcopy(31);
		    CRCregister(15) := d(3) xor CRCcopy(11) xor CRCcopy(31);
		    CRCregister(16) := d(0) xor CRCcopy(12) xor CRCcopy(28);
		    CRCregister(17) := d(1) xor CRCcopy(13) xor CRCcopy(29);
		    CRCregister(18) := d(2) xor CRCcopy(14) xor CRCcopy(30);
		    CRCregister(19) := d(3) xor CRCcopy(15) xor CRCcopy(31);
		    CRCregister(20) := CRCcopy(16);
		    CRCregister(21) := CRCcopy(17);
		    CRCregister(22) := d(0) xor CRCcopy(18) xor CRCcopy(28);
		    CRCregister(23) := d(1) xor d(0) xor CRCcopy(19) xor CRCcopy(28) xor CRCcopy(29);
		    CRCregister(24) := d(2) xor d(1) xor CRCcopy(20) xor CRCcopy(29) xor CRCcopy(30);
		    CRCregister(25) := d(3) xor d(2) xor CRCcopy(21) xor CRCcopy(30) xor CRCcopy(31);
		    CRCregister(26) := d(3) xor d(0) xor CRCcopy(22) xor CRCcopy(28) xor CRCcopy(31);
		    CRCregister(27) := d(1) xor CRCcopy(23) xor CRCcopy(29);
		    CRCregister(28) := d(2) xor CRCcopy(24) xor CRCcopy(30);
		    CRCregister(29) := d(3) xor CRCcopy(25) xor CRCcopy(31);
		    CRCregister(30) := CRCcopy(26);
		    CRCregister(31) := CRCcopy(27);

			
			END IF;	
			
			--crc_outputReg<=CRCregister;
			----------------------------------------------------------------------
        	--CRC test of validity--
--				IF (CRCregister = "11011110101110110010000011100011") THEN
--						crc_valid <= '1';
--				end if;
--				IF (NOT(CRCregister) = "11011110101110110010000011100011") THEN
--						crc_valid <= '1';
--				end if;
--				IF (CRCregister = "11000111000001001101110101111011") THEN
--						crc_valid <= '1';
--				end if;


				crc_outputReg<=CRCregister;
				IF(frame_done = '1')THEN					
--					IF ((CRCregister = "00000000000000000000000000000000") AND (data_valid = '1')) THEN
--					IF ((CRCregister = "11011110101110110010000011100011") AND (data_valid = '1')) THEN
--						crc_valid <= '1';
--					
					--IF (CRCregister = "11000111000001001101110101111011") THEN  ---check for the backward of the result that should be received
					--	crc_valid <= '1';
					--end if;
					
					IF (CRCregister = "11011110101110110010000011100011") THEN
						crc_valid <= '1';
					ELSE 
						crc_valid <= '0';
					END IF;
				check_complete <= '1';
				CRCregister := "11111111111111111111111111111111";
				END IF;
			
			---------------
      	END IF;
   END PROCESS;
END Behavior;
